package concurent

import (
	"fmt"
	"sync"
	"sync/atomic"
)

var i int32 = 100
var wga sync.WaitGroup

func addAtomic() {
	defer wga.Done()
	atomic.AddInt32(&i, 1)
}

func subAtomic() {
	defer wga.Done()
	atomic.AddInt32(&i, -1)
}

func Atomic_f2() {
	var aa int32 = 100
	// 载入操作能够保证原子的读变量的值，当读取的时候，任何其他CPU操作都无法对该变量进行读写
	fmt.Printf("atomic.LoadInt32(100): %v\n", atomic.LoadInt32(&aa)) //100
	// 操作在进行交换前首先确保变量的值未被更改，即仍然保持参数 old 所记录的值，满足此前提下才进行交换操作。CAS的做法类似操作数据库时常见的乐观锁机制。
	b := atomic.CompareAndSwapInt32(&aa, 103, 200)
	fmt.Printf("b: %v\n", b)
	//不管变量的旧值是否被改变，直接赋予新值然后返回被替换的值。
	fmt.Printf("atomic.SwapInt32(&aa, 300): %v\n", atomic.SwapInt32(&aa, 300))
	fmt.Printf("aa: %v\n", aa)
	// 确保了写变量的原子性，避免其他操作读到了修改变量过程中的脏数据。
	atomic.StoreInt32(&aa, 400)
	fmt.Printf("aa: %v\n", aa)
}

func Atomic_f1() {
	// cas原子操作 代替之前的同步锁lock    确保任一时刻只有一个goroutine对变量进行操作，善用 atomic 能够避免程序中出现大量的锁操作
	for i := 0; i < 1000; i++ {
		wga.Add(1)
		go addAtomic()
		wga.Add(1)
		go subAtomic()
	}
	wga.Wait()
	fmt.Printf("i: %v\n", i)
}
